package 函数式编程;

/*Lambda表达式使用前提：
  ●有一个接口
  ●接口中有且仅有一个抽象方法
  称之为单方法的接口即：FunctionalInterface，只有一个抽象方法，选择一个与该抽象方法签名相同的方法，除接口类方法外，可以是:
    1.类::静态方法
    2.类::实例方法
    3.对象::实例方法
只要参数和返回类型一致，用选择的方法实现接口中的抽象方法。
Lambda表达式是 方法 在调用接口中抽象方法时 直接实现接口中的抽象方法*/

//在了解Lambda之前，我们先回顾一下Java的方法。
//
//Java的方法分为实例方法，例如Integer定义的equals()方法：
//
//public final class Integer {
//  boolean equals(Object o) {
//      ...
//  }
//}
//以及静态方法，例如Integer定义的parseInt()方法：
//
//public final class Integer {
//  public static int parseInt(String s) {
//      ...
//  }
//}
//无论是实例方法，还是静态方法，本质上都相当于过程式语言的函数。例如C函数：
//
//char* strcpy(char* dest, char* src)
//只不过Java的实例方法隐含地传入了一个this变量，即实例方法总是有一个隐含参数this。
//
//函数式编程（Functional Programming）是把函数作为基本运算单元，函数可以作为变量，可以接收函数，还可以返回函数。历史上研究函数式
//编程的理论是Lambda演算，所以我们经常把支持函数式编程的编码风格称为Lambda表达式。

//《Lambda表达式》
//在Java程序中，我们经常遇到一大堆单方法接口，即一个接口只定义了一个方法：
//
//Comparator
//Runnable
//Callable
//以Comparator为例，我们想要调用Arrays.sort()时，可以传入一个Comparator实例，以匿名类方式编写如下：
//
//String[] array = ...
//Arrays.sort(array, new Comparator<String>() {
//  public int compare(String s1, String s2) {
//      return s1.compareTo(s2);
//  }
//});
//上述写法非常繁琐。从Java 8开始，我们可以用Lambda表达式替换单方法接口。改写上述代码如下：

//Lambda
/*import java.util.Arrays;
public class Lambda基础 {
  public static void main(String[] args) {
      String[] array = new String[] { "Apple", "Orange", "Banana", "Lemon" };
//      Arrays.sort(array, (s1, s2) -> {
//          return s1.compareTo(s2);
//      });
      Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));//只有一行return xxx的代码，完全可以用更简单的写法
      System.out.println(String.join(", ", array));
  }
}*/

//观察Lambda表达式的写法，它只需要写出方法定义：
//
//(s1, s2) -> {
//  return s1.compareTo(s2);
//}
//其中，参数是(s1, s2)，参数类型可以省略，因为编译器可以自动推断出String类型。-> { ... }表示方法体，所有代码写在内部即可。
//Lambda表达式没有class定义，因此写法非常简洁。
//
//如果只有一行return xxx的代码，完全可以用更简单的写法：
//
//Arrays.sort(array, (s1, s2) -> s1.compareTo(s2));
//返回值的类型也是由编译器自动推断的，这里推断出的返回值是int，因此，只要返回int，编译器就不会报错。
//
//FunctionalInterface
//我们把只定义了单方法的接口称之为FunctionalInterface，用注解@FunctionalInterface标记。例如，Callable接口：
//
//@FunctionalInterface
//public interface Callable<V> {
//  V call() throws Exception;
//}
//再来看Comparator接口：
//
//@FunctionalInterface
//public interface Comparator<T> {
//
//  int compare(T o1, T o2);
//
//  boolean equals(Object obj);//Object定义的方法
//
//  default Comparator<T> reversed() {
//      return Collections.reverseOrder(this);
//  }
//
//  default Comparator<T> thenComparing(Comparator<? super T> other) {
//      ...
//  }
//  ...
//}
//虽然Comparator接口有很多方法，但只有一个抽象方法int compare(T o1, T o2)，其他的方法都是default方法或static方法。
//另外注意到boolean equals(Object obj)是Object定义的方法，不算在接口方法内。因此，Comparator也是一个FunctionalInterface。
//
//练习
//从下载练习：使用Lambda表达式实现忽略大小写排序 （推荐使用IDE练习插件快速下载）
/*import java.util.Arrays;
//import  java.lang.String;
public class Lambda基础 {//忽略字符串大小写排序
  public static void main(String[] args) {
      String[] array = { "Apple", "Orange", "Banana", "Lemon" };
      String[] array1 = new String[] { "Apple", "Orange", "Banana", "Lemon" };
//      Arrays.sort(array, (s1, s2) -> {
//          return s1.compareTo(s2);
//      });
      Arrays.sort(array, (s1, s2) -> s1.compareToIgnoreCase(s2));//只有一行return xxx的代码，完全可以用更简单的写法
      System.out.println(String.join(", ", array));
      Arrays.sort(array1, (s1, s2) -> s1.compareTo(s2));//只有一行return xxx的代码，完全可以用更简单的写法
      System.out.println(String.join(", ", array));
  }
}*/
//
//小结
//单方法接口被称为FunctionalInterface。
//
//接收FunctionalInterface作为参数的时候，可以把实例化的匿名类改写为Lambda表达式，能大大简化代码。
//
//Lambda表达式的参数和返回值均可由编译器自动推断。
//import java.util.Arrays;
////import java.util.Comparator;
//public class Lambda基础{
//	public static void main(String[] args) {
//		String[] array1=new String[] {"apple","Orange","banana","lamon"};
//		String[] array2=new String[] {"apple","Orange","banana","lamon"};
//		Arrays.sort(array1, (s1,s2)->s1.compareTo(s2));
//		System.out.println(String.join(", ", array1));//Orange, apple, banana, lamon
//		Arrays.sort(array2, (s1,s2)->s1.compareToIgnoreCase(s2));
//		System.out.println(String.join(", ", array2));//apple, banana, lamon, Orange
//	}
//}




